#include <QtGui>
#include <QFileDialog>
#include <QLabel>
#include <QToolBar>
#include <QMessageBox>
#include <QSettings>
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QTableWidgetSelectionRange>
#include "finddialog.h"
#include "gotocelldialog.h"
#include "spreadsheet.h"
#include "extdlg.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    spreadsheet = new Spreadsheet;
    setCentralWidget(spreadsheet);

    createActions();
    createMenus();
    createContextMenu();
    createToolBars();
    createStatusBars();
    readSettings();

    findDialog = 0;

    setCurrentFile("");
    setAttribute(Qt::WA_DeleteOnClose);
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::closeEvent(QCloseEvent *event){
    if(okToContinue()){
        writeSettings();
        event->accept();
    }else{
        event->ignore();
    }
}

void MainWindow::createActions(){
    //新建文件
    newAction = new QAction(tr("新建(&N)"), this);
    newAction->setIcon(QIcon(":/myres/images/new.ico"));
    newAction->setShortcut(QKeySequence::New);
    newAction->setToolTip(tr("新建"));
    connect(newAction, SIGNAL(triggered()), this, SLOT(newFile()));

    //打开文件
    openAction = new QAction(tr("打开(&O)"), this);
    openAction->setIcon(QIcon(":/myres/images/open.ico"));
    openAction->setShortcut(QKeySequence::Open);
    openAction->setToolTip(tr("打开"));
    connect(openAction, SIGNAL(triggered()), this, SLOT(open()));

    //保存
    saveAction = new QAction(tr("保存(&S)"), this);
    saveAction->setIcon(QIcon(":/myres/images/save.ico"));
    saveAction->setShortcut(QKeySequence::Save);
    saveAction->setToolTip(tr("保存"));
    connect(saveAction, SIGNAL(triggered()), this, SLOT(save()));

    //另存为
    saveAsAction = new QAction(tr("另存为...(&A)"), this);
    saveAsAction->setIcon(QIcon(":/myres/images/save.ico"));
    saveAsAction->setShortcut(QKeySequence::SaveAs);
    saveAsAction->setToolTip(tr("另存为..."));
    connect(saveAsAction, SIGNAL(triggered()), this, SLOT(saveAs()));

    for(int i = 0; i < MaxRecentFiles; ++i){
        recentFileActions[i] = new QAction(this);
        recentFileActions[i]->setVisible(false);
        connect(recentFileActions[i], SIGNAL(triggered()),
                this, SLOT(openRecentFile()));
    }

    //关闭
    closeAction = new QAction(tr("关闭(&C)"), this);
    closeAction->setShortcut(QKeySequence::Close);
    closeAction->setToolTip(tr("关闭"));
    connect(closeAction, SIGNAL(triggered(bool)), spreadsheet, SLOT(close()));

    //退出
    exitAction = new QAction(tr("退出(&E)"), this);
    exitAction->setShortcut(tr("Ctrl+Q"));
    exitAction->setToolTip(tr("退出"));
    connect(exitAction, SIGNAL(triggered()), qApp, SLOT(closeAllWindows()));

    copyAction = new QAction(tr("复制(&C)"), this);
    copyAction->setIcon(QIcon(":/myres/images/copy.ico"));
    copyAction->setShortcut(QKeySequence::Copy);
    copyAction->setToolTip(tr("复制"));
    connect(copyAction, SIGNAL(triggered()), spreadsheet, SLOT(copy()));

    cutAction = new QAction(tr("剪切(&t)"), this);
    cutAction->setIcon(QIcon(":/myres/images/cut.ico"));
    cutAction->setShortcut(QKeySequence::Cut);
    cutAction->setToolTip(tr("剪切"));
    connect(cutAction, SIGNAL(triggered()), spreadsheet, SLOT(cut()));

    pasteAction = new QAction(tr("粘贴(&P)"), this);
    pasteAction->setIcon(QIcon(":/myres/images/paste.ico"));
    pasteAction->setShortcut(QKeySequence::Paste);
    pasteAction->setToolTip(tr("粘贴"));
    connect(pasteAction, SIGNAL(triggered()), spreadsheet, SLOT(paste()));

    deleteAction = new QAction(tr("删除(&D)"), this);
    deleteAction->setIcon(QIcon(":/myres/images/icon.ico"));
    deleteAction->setShortcut(QKeySequence::Delete);
    deleteAction->setToolTip(tr("删除"));
    connect(cutAction, SIGNAL(triggered()), spreadsheet, SLOT(del()));

    //选择行
    selectRowAction = new QAction(tr("选中整行(&R)"), this);
    selectRowAction->setToolTip(tr("选中整行"));
    connect(selectRowAction, SIGNAL(triggered()), spreadsheet, SLOT(selectCurrentRow()));

    //选择列
    selectColumnAction = new QAction(tr("选中整列(&C)"), this);
    selectColumnAction->setToolTip(tr("选中整列"));
    connect(selectColumnAction, SIGNAL(triggered()), spreadsheet, SLOT(selectCurrentColumn()));

    //全选
    selectAllAction = new QAction(tr("全选(&A)"), this);
    selectAllAction->setShortcut(QKeySequence::SelectAll);
    selectAllAction->setToolTip(tr("选中全部表格"));
    connect(selectAllAction, SIGNAL(triggered()), spreadsheet, SLOT(selectAll()));

    findAction = new QAction(tr("查找(&F)"), this);
    findAction->setIcon(QIcon(":/myres/images/find.ico"));
    findAction->setShortcut(QKeySequence::Find);
    findAction->setToolTip(tr("查找单元格"));
    connect(findAction, SIGNAL(triggered()), this, SLOT(find()));

    goToCellAction = new QAction(tr("转到(&G)"), this);
    goToCellAction->setIcon(QIcon(":/myres/images/goto.ico"));
    //goToCellAction->setShortcut(QKeySequence::);
    goToCellAction->setToolTip(tr("转到"));
    connect(goToCellAction, SIGNAL(triggered()), this, SLOT(goToCell()));

    recalculateAction = new QAction(tr("计算(&R)"), this);
    recalculateAction->setToolTip(tr("重新计算"));
    connect(recalculateAction, SIGNAL(triggered()), spreadsheet, SLOT(recalculate()));

    sortAction = new QAction(tr("排序(&S)"), this);
    sortAction->setToolTip(tr("排序"));
    connect(sortAction, SIGNAL(triggered()), this, SLOT(sort()));

    //显示网络
    showGridAction = new QAction(tr("显示/隐藏网格(&S)"), this);
    showGridAction->setCheckable(true);
    showGridAction->setChecked(spreadsheet->showGrid());
    showGridAction->setToolTip(tr("显示/隐藏网格"));
    connect(showGridAction, SIGNAL(triggered(bool)), spreadsheet, SLOT(setShowGrid(bool)));

    //自动计算
    autoRecalcAction = new QAction(tr("自动重算"), this);
    autoRecalcAction->setIcon(QIcon(":/myres/images/calculate.ico"));
    autoRecalcAction->setCheckable(true);
    autoRecalcAction->setChecked(spreadsheet->autoRecalculate());
    autoRecalcAction->setToolTip(tr("是否自动重新计算"));
    connect(autoRecalcAction, SIGNAL(triggered(bool)), spreadsheet, SLOT(setAutoRecalculate(bool)));

    //关于
    aboutAction = new QAction(tr("关于(&A)"), this);
    aboutAction->setToolTip(tr("关于表格应用"));
    connect(aboutAction, SIGNAL(triggered()), this, SLOT(about()));

    //关于QT对话框
    aboutQtAction = new QAction(tr("关于QT(&Q)"), this);
    aboutQtAction->setToolTip(tr("关于QT"));
    connect(aboutQtAction, SIGNAL(triggered()), qApp, SLOT(aboutQt()));
}

void MainWindow::createMenus(){
    fileMenu = menuBar()->addMenu(tr("文件(&F)"));
    fileMenu->addAction(newAction);
    fileMenu->addAction(openAction);
    fileMenu->addAction(saveAction);
    fileMenu->addAction(saveAsAction);

    separatorAction = fileMenu->addSeparator();
    for(int i = 0; i < MaxRecentFiles; ++i){
        fileMenu->addAction(recentFileActions[i]);
    }
    fileMenu->addSeparator();
    fileMenu->addAction(exitAction);

    editMenu = menuBar()->addMenu(tr("编辑(&E)"));
    editMenu->addAction(cutAction);
    editMenu->addAction(copyAction);
    editMenu->addAction(pasteAction);
    editMenu->addAction(deleteAction);

    selectSubMenu = editMenu->addMenu(tr("选择(&S)"));
    selectSubMenu->addAction(selectRowAction);
    selectSubMenu->addAction(selectColumnAction);
    selectSubMenu->addAction(selectAllAction);

    editMenu->addSeparator();
    editMenu->addAction(findAction);
    editMenu->addAction(goToCellAction);

    toolsMenu = menuBar()->addMenu(tr("工具(&T)"));
    toolsMenu->addAction(recalculateAction);
    toolsMenu->addAction(sortAction);

    optionsMenu = menuBar()->addMenu(tr("选项(&O)"));
    optionsMenu->addAction(showGridAction);
    optionsMenu->addAction(autoRecalcAction);

    menuBar()->addSeparator();

    helpMenu = menuBar()->addMenu(tr("帮助(&H)"));
    helpMenu->addAction(aboutAction);
    helpMenu->addAction(aboutQtAction);
}

void MainWindow::createContextMenu(){
    spreadsheet->addAction(cutAction);
    spreadsheet->addAction(copyAction);
    spreadsheet->addAction(pasteAction);
    spreadsheet->setContextMenuPolicy(Qt::ActionsContextMenu);
}

void MainWindow::createToolBars(){
    fileToolBar = addToolBar(tr("文件(&F)"));
    fileToolBar->addAction(newAction);
    fileToolBar->addAction(openAction);
    fileToolBar->addAction(saveAction);

    editToolBar = addToolBar(tr("&Edit"));
    editToolBar->addAction(cutAction);
    editToolBar->addAction(copyAction);
    editToolBar->addAction(pasteAction);

    editToolBar->addSeparator();

    editToolBar->addAction(findAction);
    editToolBar->addAction(goToCellAction);
}

void MainWindow::createStatusBars(){
    locationLabel = new QLabel(tr(" W999 "));
    locationLabel->setAlignment(Qt::AlignCenter);
    locationLabel->setMinimumSize(locationLabel->sizeHint());

    formulaLabel = new QLabel;
    formulaLabel->setIndent(3);


    statusBar()->addWidget(locationLabel);
    statusBar()->addWidget(formulaLabel, 1);

    connect(spreadsheet, SIGNAL(currentCellChanged(int, int, int, int)),
            this, SLOT(updateStatusBar()));

    connect(spreadsheet, SIGNAL(modified()),
            this, SLOT(spreadsheetModified()));

    updateStatusBar();
}

void MainWindow::readSettings(){
    QSettings settings("Software Inc.", "Spreadsheet");
    restoreGeometry(settings.value("geometry").toByteArray());

    recentFiles = settings.value("recentFiles").toStringList();
    updateRecentFileActions();

    bool showGrid = settings.value("showGrid", true).toBool();
    showGridAction->setChecked(showGrid);

    bool autoRecalc = settings.value("autoRecalc", true).toBool();
    autoRecalcAction->setChecked(autoRecalc);
}

void MainWindow::writeSettings(){
    QSettings settings("Software Inc.", "Spreadsheet");
    settings.setValue("geometry", saveGeometry());
    settings.setValue("recentFiles", recentFiles);
    settings.setValue("showGrid", showGridAction->isChecked());
    settings.setValue("autoRecalc", autoRecalcAction->isChecked());
}

bool MainWindow::okToContinue(){
    if(isWindowModified()){
        int r = QMessageBox::warning(this, tr("Spreadsheet"),
                                     tr("文档已被修改，你想保存这个修改吗？"),
                                     QMessageBox::Yes | QMessageBox::No | QMessageBox::Cancel);
        if(r == QMessageBox::Yes){
            return save();
        } else if(QMessageBox::Cancel == r){
            return false;
        }
    }
     return true;
}

bool MainWindow::loadFile(const QString &fileName){
    if(!spreadsheet->readFile(fileName)){
        statusBar()->showMessage("Loading canceled", 2000);
        return false;
    }
    setCurrentFile(fileName);
    statusBar()->showMessage("File loaded", 2000);
    return true;
}

bool MainWindow::saveFile(const QString &fileName){
    if(!spreadsheet->writeFile(fileName)){
        statusBar()->showMessage(tr("Saving canceled"), 2000);
        return false;
    }
    setCurrentFile(fileName);
    statusBar()->showMessage(tr("File Saved"), 2000);
    return true;
}

bool MainWindow::save(){
    if(curFile.isEmpty()){
        return saveAs();
    }else{
        return saveFile(curFile);
    }
}

bool MainWindow::saveAs(){
    QString fileName = QFileDialog::getSaveFileName(this, tr("文件另存为"),
                                                ".", tr("Spreadsheet file(*.sp)"));
    if(fileName.isEmpty()){
        return false;
    }
    return saveFile(fileName);
}

void MainWindow::find(){
    if(!findDialog){
        findDialog = new FindDialog(this);
        connect(findDialog, SIGNAL(findNext(const QString &, Qt::CaseSensitivity)),
                spreadsheet, SLOT(findNext(const QString &, Qt::CaseSensitivity)));
        connect(findDialog, SIGNAL(findPrevious(const QString &, Qt::CaseSensitivity)),
                spreadsheet, SLOT(findPrevious(const QString &, Qt::CaseSensitivity)));
    }
    findDialog->show();
    findDialog->raise();
    findDialog->activateWindow();
}

void MainWindow::goToCell(){
    GoToCellDialog gotoDialog(this);
    //GoToCellDialog gotoDialog = new GoToCellDialog(this);
    if(gotoDialog.exec()){  //exec模态对话框;show非模态对话框
        QString str = gotoDialog.lineEdit->text().toUpper();
        spreadsheet->setCurrentCell(str.mid(1).toInt() - 1, str[0].unicode() - 'A');
    }
    //delete gotoDialog;
}

void MainWindow::sort(){
    ExtDlg sortDialog(this);

    QTableWidgetSelectionRange range = spreadsheet->selectedRange();
    sortDialog.setColumnRange('A' + range.leftColumn(),
                              'A' + range.rightColumn());
    if(sortDialog.exec()){
        SpreadsheetCompare compare;

        compare.keys[0] = sortDialog.cbxPrimaryCol->currentIndex();
        compare.keys[1] = sortDialog.cbxSecondaryCol->currentIndex();
        compare.keys[2] = sortDialog.cbxTertiaryCol->currentIndex();
        compare.ascending[0] = (sortDialog.cbxPrimaryCol->currentIndex() == 0);
        compare.ascending[1] = (sortDialog.cbxSecondaryCol->currentIndex() == 0);
        compare.ascending[2] = (sortDialog.cbxTertiaryCol->currentIndex() == 0);
        spreadsheet->sort(compare);
    }
}

void MainWindow::about(){
    QMessageBox::about(this, tr("关于表格应用"),
                       tr("<h1>表格应用 v1.0</h1>"
                          "<p>Copyright &copy;2022 Software Inc."
                          "<p>表格应用是基于QT开发的一款小型应用."));
}

void MainWindow::openRecentFile(){
    if(okToContinue()){
        QAction *action = qobject_cast<QAction *>(sender());
        if(action){
            loadFile(action->data().toString());
        }
    }
}

void MainWindow::setCurrentFile(const QString &fileName){
    curFile = fileName;
    setWindowModified(false);
    QString shownName = tr("未命名");
    if(!curFile.isEmpty()){
        shownName = strippedName(curFile);
        recentFiles.removeAll(curFile);
        recentFiles.prepend(curFile);
        updateRecentFileActions();
    }

    setWindowTitle(tr("%1[*] - %2").arg(shownName).arg(tr("电子制表软件")));
}

void MainWindow::updateRecentFileActions(){
    QMutableStringListIterator i(recentFiles);
    while(i.hasNext()){
        if(!QFile::exists(i.next())){
            i.remove();
        }
    }

    for(int j = 0; j < MaxRecentFiles; ++j){
        if(j < recentFiles.count()){
            QString text = tr("&%1 %2").arg(j+1).arg(strippedName(recentFiles[j]));
            recentFileActions[j]->setText(text);
            recentFileActions[j]->setData(recentFiles[j]);
            recentFileActions[j]->setVisible(true);
        }else{
            recentFileActions[j]->setVisible(false);
        }
    }
    separatorAction->setVisible(!recentFiles.isEmpty());
}

QString MainWindow::strippedName(const QString &fullFileName){
    return QFileInfo(fullFileName).fileName();
}

void MainWindow::updateStatusBar(){
    locationLabel->setText(spreadsheet->currentLocation());
    formulaLabel->setText(spreadsheet->currentFormula());
}

void MainWindow::spreadsheetModified(){
    setWindowModified(true);
    updateStatusBar();
}

void MainWindow::newFile(){

    if(okToContinue()){
        spreadsheet->clear();
        setCurrentFile("");
    }
}

void MainWindow::close(){

}

void MainWindow::open(){
    if(okToContinue()){

        QString fileName = QFileDialog::getOpenFileName(this, tr("Open spreadsheet"),
                                                          ".", tr("Spread files(*.sp)\n"
                                                                  "Comma-separated values files(*.csv)\n"));
        if(!fileName.isEmpty()){
            loadFile(fileName);
        }
    }
}
